package com.ray.project.oceanicwaveinformation;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.ray.project.gpslocation.GpsLocationHelper;
import com.ray.project.ndbc.OceanicBuoyDataGetter;
import com.ray.project.oceanicbuoy.OceanicBuoy;
import com.ray.project.oceanicwaveinformation.R;

import java.util.ArrayList;


public class OceanicBuoyMapViewActivity extends MapActivity {

    private MapController mapviewController;
    private LocationManager geoLocationManager;
    private LocationProvider geoLocationProvider;
    private MapView mapView;
    private ViewGroup mapZoom;
    private Overlay oceanicBuoyOverlay;
    private ProgressDialog progressDialog;
    private Drawable defaultMapMarker;
    private ArrayList<OceanicBuoyOverlayItem> oceanicBuoys;
    
    private static final int MENU_SET_TO_SATELLITE = 1;
    private static final int MENU_SET_TO_MAP = 2;
   
    private final Handler threadActivityHandler = new Handler() {

        @Override
        public void handleMessage(final Message msg) {

            progressDialog.dismiss();

            if (mapView.getOverlays().contains(oceanicBuoyOverlay)) {
                mapView.getOverlays().remove(oceanicBuoyOverlay);
            }

            oceanicBuoyOverlay = new OceanicBuoyItemizedOverlay(oceanicBuoys, defaultMapMarker, OceanicBuoyMapViewActivity.this);
            mapView.getOverlays().add(oceanicBuoyOverlay);

            mapView.invalidate();
        }
    };

    private final LocationListener locationListenerGetBuoyData = new LocationListener() {

        public void onLocationChanged(final Location loc) {
            int lat = (int) (loc.getLatitude() * GpsLocationHelper.MULTIPLIER);
            int lon = (int) (loc.getLongitude() * GpsLocationHelper.MULTIPLIER);
            
            GeoPoint geoPoint = new GeoPoint(lat, lon);
            // Get the Oceanic Buoy data using the latitude and longitude coded into the GeoPoint
            getOceanicBuoyData(geoPoint);
        }

        // These three overrides are required though not used in this app.
        public void onProviderDisabled(final String s) {
        }

        public void onProviderEnabled(final String s) {
        }

        public void onStatusChanged(final String s, final int i, final Bundle b) {
        }
    };

    private final LocationListener locationListenerRecenterMap = new LocationListener() {
      
        public void onLocationChanged(final Location location) {
            int latitude = (int) (location.getLatitude() * GpsLocationHelper.MULTIPLIER);
            int longitude = (int) (location.getLongitude() * GpsLocationHelper.MULTIPLIER);           
            GeoPoint geoLocationPoint = new GeoPoint(latitude, longitude);
            mapviewController.animateTo(geoLocationPoint);
        }

        // These three overrides are required though not used in this app.
        public void onProviderDisabled(final String s) {
        }

        public void onProviderEnabled(final String s) {
        }

        public void onStatusChanged(final String s, final int i, final Bundle b) {
        }
    };

    @Override
    public void onCreate(final Bundle icicle) {
        super.onCreate(icicle);        
        this.setContentView(R.layout.oceanic_mapview_activity);

        this.mapView = (MapView) findViewById(R.id.map_view);
        this.mapZoom = (ViewGroup) findViewById(R.id.zoom);
        this.mapZoom.addView(this.mapView.getZoomControls());

        this.defaultMapMarker = getResources().getDrawable(R.drawable.buoy);
        this.defaultMapMarker.setBounds(0, 0, this.defaultMapMarker.getIntrinsicWidth(), this.defaultMapMarker
            .getIntrinsicHeight());

        this.oceanicBuoys = new ArrayList<OceanicBuoyOverlayItem>();
    }

    @Override
    public void onStart() {
        super.onStart();
        this.geoLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        this.geoLocationProvider = this.geoLocationManager.getProvider(LocationManager.GPS_PROVIDER);

        if (this.geoLocationProvider != null) {
            this.geoLocationManager.requestLocationUpdates(this.geoLocationProvider.getName(), 3000, 185000,
                this.locationListenerGetBuoyData);
            this.geoLocationManager.requestLocationUpdates(this.geoLocationProvider.getName(), 3000, 1000,
                this.locationListenerRecenterMap);
        } else {           
            Toast.makeText(this,
                "Application can't continue, GPS location provider is unavailable.",
                Toast.LENGTH_SHORT).show();
            finish();
        }

        GeoPoint lastKnownGeoPoint = getLastKnownGeoPoint();
        this.mapviewController = this.mapView.getController();
        this.mapviewController.setZoom(10);
        this.mapviewController.animateTo(lastKnownGeoPoint);
        getOceanicBuoyData(lastKnownGeoPoint);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (this.progressDialog.isShowing()) {
            this.progressDialog.dismiss();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (this.progressDialog.isShowing()) {
            this.progressDialog.dismiss();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(0, OceanicBuoyMapViewActivity.MENU_SET_TO_MAP, 0, "Map").setIcon(android.R.drawable.ic_menu_mapmode);
        menu.add(0, OceanicBuoyMapViewActivity.MENU_SET_TO_SATELLITE, 0, "Satellite").setIcon(android.R.drawable.ic_menu_mapmode);      
        return true;
    }
        
    @Override
    public boolean onMenuItemSelected(final int featureId, final MenuItem item) {
        switch (item.getItemId()) {
            case OceanicBuoyMapViewActivity.MENU_SET_TO_MAP:
                this.mapView.setSatellite(false);
                break;
            case OceanicBuoyMapViewActivity.MENU_SET_TO_SATELLITE:
                this.mapView.setSatellite(true);
                break;
        }
        return super.onMenuItemSelected(featureId, item);
    }

    // Must be overridden but not used in this application. Used by Google Maps for generating driving directions.
    @Override
    public boolean isRouteDisplayed() {
        return false;
   }

    private GeoPoint getLastKnownGeoPoint() {
        GeoPoint lastKnownLocationPoint = null;   
        Location lastKnownLocation;
        
        SharedPreferences useGps = PreferenceManager.getDefaultSharedPreferences(this);
 	    Boolean useGpsTest = useGps.getBoolean("PREF_USE_GPS", true); 	   
 	    
 	    if (useGpsTest==true) {
 	    	lastKnownLocation = this.geoLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
 	    	if (lastKnownLocation == null) {
 	    		lastKnownLocation = this.geoLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
 	    	}
 	    	if (lastKnownLocation != null) {
 	            lastKnownLocationPoint = GpsLocationHelper.getGeoPoint(lastKnownLocation);
 	    	}
 	    	else {
 	    		lastKnownLocationPoint = GpsLocationHelper.HONOLULU;
 	    		Toast.makeText(this,
 	    				"Application cannot determine your current location - setting location to Honoluly, Hawaii. Select fixed locations from the Settings screen.",
 	    				Toast.LENGTH_LONG).show();
 	    	} 	    		
 	    }
 	    else {
 	    	SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 	 	    final String pref = prefs.getString("PREF_DEFAULT_LOCATION", "defValue");
 	 	    
 	 	    String latitude = pref.substring(0, pref.indexOf(":"));
 	 	    String longitude = pref.substring(pref.indexOf(":")+1);
 	 	    
 	 	    lastKnownLocationPoint = GpsLocationHelper.getPreferenceGeoPoint(latitude, longitude);
 	    }   
      
        return lastKnownLocationPoint;
    }

    private void getOceanicBuoyData(final GeoPoint point) {
       this.progressDialog = ProgressDialog.show(this, "Processing . . .", "Getting buoy data", true, false);

       // Get the radius from the Android Preferences
       SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
	   final String pref = prefs.getString("PREF_BUOY_RADIUS", "defValue");
       
        new Thread() {

            @Override
            public void run() {                
                String lats = GpsLocationHelper.parseGeoPoint(point.getLatitudeE6() / GpsLocationHelper.MULTIPLIER, true);
                String lons = GpsLocationHelper.parseGeoPoint(point.getLongitudeE6() / GpsLocationHelper.MULTIPLIER, false);                       
                
                OceanicBuoyDataGetter getter = new OceanicBuoyDataGetter(lats, lons, pref);                
                ArrayList<OceanicBuoy> buoyDataList = getter.getBuoyData();                              
                oceanicBuoys = getOceanicBuoyOverlayItems(buoyDataList);              
                threadActivityHandler.sendEmptyMessage(1);
            };
        }.start();
    }

    private ArrayList<OceanicBuoyOverlayItem> getOceanicBuoyOverlayItems(ArrayList<OceanicBuoy> oceanicBuoyDataList) {
        ArrayList<OceanicBuoyOverlayItem> oceanicBuoyOverylayItemList = new ArrayList<OceanicBuoyOverlayItem>();
        for (OceanicBuoy bd : oceanicBuoyDataList) {
            if (bd.getGeoRssPoint() != null) {
                GeoPoint geoPoint = GpsLocationHelper.getGeoPoint(bd.getGeoRssPoint());
                if (geoPoint != null) {
                    OceanicBuoyOverlayItem boi = new OceanicBuoyOverlayItem(geoPoint, bd);
                    oceanicBuoyOverylayItemList.add(boi);
                } else {
              }
            } else {
 
            }
        }
        return oceanicBuoyOverylayItemList;
    }
}
